package com.mutouren.web;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.tuple.ImmutablePair;
import org.springframework.context.ApplicationContext;

import com.google.common.cache.Cache;
import com.mutouren.common.cache.local.GuavaCacheUtils;
import com.mutouren.common.cache.local.GuavaCacheUtils.ExpireType;
import com.mutouren.modules.org.model.Function;
import com.mutouren.modules.org.service.FunctionService;
import com.mutouren.modules.org.service.PersonService;

public class AuthorityManager {

	private static PersonService personService;	
	private static FunctionService functionService;		

	private static Cache<String, Object> cache = GuavaCacheUtils.createCache(5, TimeUnit.MINUTES, ExpireType.expireAfterWrite);	

	public static void init(ApplicationContext context) {		
		AuthorityManager.personService = context.getBean(PersonService.class);
		AuthorityManager.functionService = context.getBean(FunctionService.class);
	}

	private static ImmutablePair<List<Function>, Map<String, Integer>> toImmutablePair(List<Function> listFunction) {
		Map<String, Integer> mapFunction = new HashMap<String, Integer>();
		for(Function obj : listFunction) {
			mapFunction.put(obj.getUrl(), obj.getFuncId());
		}
		
		return new ImmutablePair<List<Function>, Map<String, Integer>>(listFunction, mapFunction);
	}

	private synchronized static ImmutablePair<List<Function>, Map<String, Integer>> getFunctionPairOfApp() {
		String key = String.format("appAlias_%s", SystemConfig.getAppAlias());
		
		@SuppressWarnings("unchecked")
		ImmutablePair<List<Function>, Map<String, Integer>> cacheFunctions = 
			(ImmutablePair<List<Function>, Map<String, Integer>>)cache.getIfPresent(key);
		if (cacheFunctions != null) {
			return cacheFunctions;
		}
		
		//System.out.println("load...");
		List<Function> listFunction = functionService.selectByAppId(SystemConfig.getApp().getAppId(), false);
		ImmutablePair<List<Function>, Map<String, Integer>> pair = toImmutablePair(listFunction);
		cache.put(key, pair);
		return pair;	
	}
	
	private static Map<String, Integer> getMapUrlOfApp() {
		return getFunctionPairOfApp().getRight();
	}
	
//	private static List<Function> getAllFunctionOfApp() {
//		return getFunctionPairOfApp().getLeft();
//	}	
	
	private synchronized static int[] getFunctionIdsOfUser(int userId) {
		String key = String.format("userId_%s", userId);
		
		int[] cacheFunctionIds = (int[])cache.getIfPresent(key);
		if (cacheFunctionIds != null) {
			return cacheFunctionIds;
		}		
		
		List<Function> listFunction = personService.selectFunction(userId, SystemConfig.getApp().getAppId());
		int[] ids = new int[listFunction.size()];		
		for(int i = 0; i < listFunction.size(); i++) {
			ids[i] = listFunction.get(i).getFuncId();
		}		
		cache.put(key, ids);
		return ids;	
	}	

	public static boolean permit(HttpServletRequest request, int userId) {
		String actionName = request.getRequestURI().replace(request.getContextPath(),"");
		
		Map<String, Integer> mapUrl = getMapUrlOfApp();
		int[] userFunctionIds = getFunctionIdsOfUser(userId);
		
		Integer functionId = mapUrl.get(actionName);
		if (functionId == null) {
			return true;
		} else {
			for(int id : userFunctionIds) {
				if (functionId == id) {
					return true;
				}
			}
			return false;	
		}
	}

}
